XRP Arcade Drive
Overviewβ
You saw that tank drive gave you a ton of control, but it was really hard to drive smoothly. Then, button drive was super easy to use, but you lost a lot of that fine-tuned control. Now, let's try arcade drive to find a good mix!
Arcade drive may be more familiar, because it is the basis of many video games. One joystick moves the robot forward and backward, and the same joystick turns left and right. To do this, we will use the joystick's up/down value to set a base speed for both motors, and the joystick's left/right value to increase or decrease the motor speeds to turn the robot. This control scheme offers less driver control, but it's easy to learn and many drivers enjoy it.

If you have already implemented the Tank Drive tutorial, you can build on that project to add Arcade Drive functionality. No need to create a new project!
The Pre-Code Workout πβ
Before writing any code, let's plan our arcadeDrive method. This method will translate joystick inputs into motor speeds, combining forward/backward motion and turning into a single control scheme.
Inputs and Outputsβ
The method needs two inputs from the joystick and will produce two outputs to control the motors.
-
Inputs:
speed(double): Controls forward/backward motion (from the joystick's Y-axis).turning(double): Controls turning motion (from the joystick's X-axis).
-
Outputs:
- Left Motor Speed: Calculated as
speed - turning. - Right Motor Speed: Calculated as
speed + turning.
- Left Motor Speed: Calculated as
Tasks:β
- Read joystick Y-axis for forward/backward motion.
- Read joystick X-axis for turning.
- Calculate left and right motor speeds based on the inputs.
- Set the motor speeds to control the robot.
Flow Chart:β
Flow Chart π
Time to Start Codingβ
Clone Repositoryβ
Before we start coding, you need to get the robot code on your computer. This is called cloning a repository.
TBD β Java starter repository URL to be added. A Java version of the XRP tutorial project does not exist yet. Once it is created, the clone URL will be added here.
For detailed instructions on how to clone the repository, please follow the guide for cloning a repository.
Once your repository is cloned, return to this tutorial to write your first lines of Java code.
Create a Drivetrain Subsystemβ
The first step is to create a subsystem for our drivetrain. See How to Create a Subsystem for instructions on how to do this. You should name your subsystem Drivetrain.
The Drivetrain.java Fileβ
For more information on what a class is, see What is a Class.
Navigate to your Drivetrain.java file. Here are the steps you need to follow:
-
Import the XRP Motor class.
Add the necessaryimportstatement at the top of your file so you can use the XRP motor objects.
If you need help, see the XRP Motor Quick Reference. -
Add the motor objects.
Create objects for the left and right motors.
For more details, refer to the XRP Motor Quick Reference. -
Add the arcadeDrive method.
In your class, add thearcadeDrivemethod.
If you need help with Java methods, check the Methods Quick Reference. -
Add the method body.
This is where we will do the math to get the left and right motor speeds:
// Set the speed of the left and right motors based on the arcade drive inputs
double leftMotor = speed - turning;
double rightMotor = speed + turning;
m_leftMotor.set(leftMotor);
m_rightMotor.set(rightMotor);
- Invert the left motor.
We need to invert the left motor in the constructor so both motors drive in the same direction. The left and right motors are mounted facing opposite directions on the XRP robot, so we need to invert one of them. We put this in the constructor because it only needs to be set once when the subsystem is created, rather than every time we call thearcadeDrivemethod. Add this to theDrivetrain()constructor:
public Drivetrain() {
m_leftMotor.setInverted(true);
}
Your Drivetrain.java file should look like this.
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot.subsystems;
import edu.wpi.first.wpilibj.xrp.XRPMotor;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class Drivetrain extends SubsystemBase {
// This creates an object for the left and right motor
private final XRPMotor m_leftMotor = new XRPMotor(0);
private final XRPMotor m_rightMotor = new XRPMotor(1);
public Drivetrain() {
m_leftMotor.setInverted(true); // Invert the left motor here
}
// arcadeDrive has two inputs: speed and turning.
public void arcadeDrive(double speed, double turning) {
// Set the speed of the left and right motors based on the arcade drive inputs
double leftMotor = speed - turning;
double rightMotor = speed + turning;
m_leftMotor.set(leftMotor);
m_rightMotor.set(rightMotor);
}
// This method will be called once per scheduler run
@Override
public void periodic() {}
}
The RobotContainer.java Fileβ
The RobotContainer.java file is where you set up your robot's main structure, including subsystems and input devices.
Navigate to your RobotContainer.java file. Here's what you need to do:
-
Import the Drivetrain Subsystem
Add animportstatement for yourDrivetrainclass so you can use your drivetrain subsystem. If you need help, see Import Statements -
Create the Drivetrain Subsystem
Add a field for yourDrivetrainsubsystem. If you need help see Fields -
Import and create your Xbox controller
Import and create aCommandXboxController. If you need help see Xbox Controller -
Import RunCommand
Addimport edu.wpi.first.wpilibj2.command.RunCommand;for creating inline commands. -
Set the default command
Set up the drivetrain's default command to continuously run arcade drive with joystick inputs. Add this code to theconfigureBindings()method:m_drivetrain.setDefaultCommand(new RunCommand(() -> m_drivetrain.arcadeDrive(m_driverController.getLeftY(), m_driverController.getLeftX()),m_drivetrain));This creates a
RunCommandthat calls thearcadeDrivemethod with the left joystick's Y-axis (forward/backward) and X-axis (turning) values. The command runs continuously as the drivetrain's default behavior.
Your RobotContainer.java file should look like this:
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.RunCommand;
import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
import frc.robot.subsystems.Drivetrain;
public class RobotContainer {
private final Drivetrain m_drivetrain = new Drivetrain();
private final CommandXboxController m_driverController = new CommandXboxController(0);
public RobotContainer() {
configureBindings();
}
private void configureBindings() {
m_drivetrain.setDefaultCommand(new RunCommand(
() -> m_drivetrain.arcadeDrive(m_driverController.getLeftY(), m_driverController.getLeftX()),
m_drivetrain));
}
public Command getAutonomousCommand() {
return null;
}
}
Time to test your codeβ
Now that you've implemented the arcade drive functionality, it's time to test your code!
Need help connecting to the XRP robot? See: Connecting to the XRP Robot
Deploy and Testβ
Great job writing your first XRP code. it is time to test your code. Go to XRP Run Code to test your code
Testing Checklistβ
- Robot moves forward when you push the left joystick forward (up)
- Robot moves backward when you pull the left joystick backward (down)
- Robot turns right when you push the left joystick to the right
- Robot turns left when you push the left joystick to the left
- Robot can move forward/backward and turn at the same time
Challenge: Refine Your Arcade Drive πβ
Ready to polish the feel of arcade drive? Pick a few of these miniβchallenges:
- Add overall scaling constants in
Constants.java(e.g., kDriveScale, kTurnScale) and multiply raw joystick values before combining; tune until it feels natural. - Add input deadband (ignore tiny joystick values) to reduce drift.
- Prevent motor outputs from exceeding [-1, 1] after combining forward and turn.
Tipsβ
- Change one thing at a time; test immediately.
- Start conservative (lower speeds) then build up.
- Keep notes: which adjustment made driving smoother?